<template>
  <div class="file-manager-container auto-height-container">
    <NavigationBar :current-path="currentPath" @navigate="navigateTo" @upload="handleUpload"
      @create-folder="createFolder" @refresh="refreshList" />

    <div class="content-area">
      <FileList :file-list="fileList" :loading="loading" @dblclick="handleItemDblClick"
        @contextmenu="handleContextMenu" />
    </div>

    <ContextMenu :visible="contextMenuVisible" :style="contextMenuStyle" :selected-item="selectedItem"
      @command="handleContextMenuAction" />

    <!-- 使用上传对话框组件 -->
    <UploadDialog v-model="uploadDialogVisible" :upload-url="uploadUrl" :headers="headers" :upload-data="uploadData"
      @success="handleUploadSuccess" />

    <!-- 使用新建文件夹对话框组件 -->
    <CreateFolderDialog v-model="folderDialogVisible" @confirm="confirmCreateFolder" />

    <!-- 使用属性对话框组件 -->
    <PropertiesDialog v-model="propertiesDialogVisible" :folder-info="folderInfo" />

    <FileInfoDialog v-model="fileInfoDialogVisible" :file-info="fileInfo" :folder-info="folderInfo" />

    <!-- 使用统一的预览组件 -->
    <PreviewDialog v-model:visible="previewVisible" :url="previewUrl" :type="previewType" :title="previewTitle"
      :path="previewPath" />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElImageViewer } from 'element-plus'
import NavigationBar from './components/NavigationBar.vue'
import FileList from './components/FileList.vue'
import ContextMenu from './components/ContextMenu.vue'
import UploadDialog from './components/UploadDialog.vue'
import CreateFolderDialog from './components/CreateFolderDialog.vue'
import PropertiesDialog from './components/PropertiesDialog.vue'
import FileInfoDialog from './components/FileInfoDialog.vue'
import PreviewDialog from './components/PreviewDialog.vue'
import { getFileList, createFolder as createFolderApi, deleteFile, deleteDirectory, getFolderInfo, getFileInfo, getPreviewUrl, getDownloadUrl } from '/@/api/oss'
import { useUserStore } from '/@/store/modules/user'
import type { OSSFile, OSSDirectory, OSSResponse, FolderInfo, FileInfo } from './types'
import { getFileType, isPreviewableType } from './types'

const currentPath = ref('/')
const fileList = ref<(OSSFile | OSSDirectory)[]>([])
const uploadDialogVisible = ref(false)
const folderDialogVisible = ref(false)
const contextMenuVisible = ref(false)
const selectedItem = ref<OSSFile | OSSDirectory | null>(null)
const propertiesDialogVisible = ref(false)
const folderInfo = ref<FolderInfo | null>(null)
const fileInfoDialogVisible = ref(false)
const fileInfo = ref<FileInfo | null>(null)

// 上传相关配置
const userStore = useUserStore()
const baseUrl = import.meta.env.VITE_APP_BASE_URL
const uploadUrl = `${baseUrl}/admin/oss/upload`
const headers: Record<string, string> = {
  Authorization: String(userStore.token)
}
const uploadData = ref({
  path: currentPath
})

const contextMenuStyle = ref({
  top: '0px',
  left: '0px'
})

// 分页相关参数
const pageParams = ref({
  marker: '',
  maxKeys: 100
})

const loading = ref(false)

// 预览相关状态
const previewVisible = ref(false)
const previewUrl = ref('')
const previewType = ref('')
const previewTitle = ref('')
const previewPath = ref('')

// 获取文件列表
const fetchFileList = async () => {
  loading.value = true
  try {
    const prefix = currentPath.value.replace(/^\//, '')
    const res = await getFileList({
      prefix,
      marker: pageParams.value.marker,
      maxKeys: pageParams.value.maxKeys
    })
    const ossData = res.data as OSSResponse

    // 合并文件和文件夹列表，并添加必要的属性
    const directories = ossData.dirs.map(dir => ({
      ...dir,
      type: 'folder',
      size: 0,
      updateTime: '-'
    }))

    const files = ossData.files.map(file => {
      const extension = file.name.split('.').pop() || ''
      return {
        ...file,
        type: getFileType(extension),  // 根据扩展名判断类型
        updateTime: new Date(file.lastModified).toLocaleString(),
        extension
      }
    })

    fileList.value = [...directories, ...files]

    // 更新下一页的 marker
    if (ossData.nextMarker) {
      pageParams.value.marker = ossData.nextMarker
    }
  } catch (error) {
    ElMessage.error('获取文件列表失败')
  } finally {
    loading.value = false
  }
}

// 导航到指定路径时重置分页参数
const navigateTo = (path: string) => {
  currentPath.value = path.endsWith('/') ? path : `${path}/`
  pageParams.value.marker = '' // 重置 marker
  fetchFileList()
}

// 处理上传
const handleUpload = () => {
  uploadDialogVisible.value = true
}

// 上传成功回调
const handleUploadSuccess = () => {
  ElMessage.success('上传成功')
  uploadDialogVisible.value = false
  fetchFileList()
}

// 创建文件夹
const createFolder = () => {
  folderDialogVisible.value = true
}

// 确认创建文件夹
const confirmCreateFolder = async (name: string) => {
  try {
    await createFolderApi({
      path: currentPath.value,
      name
    })
    ElMessage.success('创建成功')
    folderDialogVisible.value = false
    fetchFileList()
  } catch (error) {
    ElMessage.error('创建失败')
  }
}

// 处理双击
const handleItemDblClick = async (item: OSSFile | OSSDirectory) => {
  if ('type' in item && item.type === 'folder') {
    navigateTo(item.path)
  } else if ('type' in item) {
    try {
      const { data } = await getPreviewUrl(item.path)
      if (isPreviewableType(item.type, item.extension)) {
        previewUrl.value = data.url
        previewType.value = data.type
        previewTitle.value = item.name
        previewPath.value = item.path
        previewVisible.value = true
      } else {
        handleDownload(item.path)
      }
    } catch (error) {
      ElMessage.error('获取预览地址失败')
    }
  }
}

// 处理右键菜单
const handleContextMenu = (event: MouseEvent, item: OSSFile | OSSDirectory) => {
  event.preventDefault()
  selectedItem.value = item
  contextMenuVisible.value = true
  contextMenuStyle.value = {
    top: `${event.clientY}px`,
    left: `${event.clientX}px`
  }
}

// 处理右键菜单命令
const handleContextMenuAction = async (command: string) => {
  if (!selectedItem.value) return

  try {
    switch (command) {
      case 'open':
        if ('type' in selectedItem.value && selectedItem.value.type === 'folder') {
          navigateTo(selectedItem.value.path)
        }
        break
      case 'download':
        if ('type' in selectedItem.value) {
          handleDownload(selectedItem.value.path)
        }
        break
      case 'delete':
        if ('type' in selectedItem.value) {
          if (selectedItem.value.type === 'folder') {
            await deleteDirectory(selectedItem.value.path)
          } else {
            await deleteFile(selectedItem.value.path)
          }
          ElMessage.success('删除成功')
          fetchFileList()
        }
        break
      case 'properties':
        if ('type' in selectedItem.value && selectedItem.value.type === 'folder') {
          const res = await getFolderInfo(selectedItem.value.path)
          folderInfo.value = res.data
          propertiesDialogVisible.value = true
        }
        break
      case 'info':
        if ('type' in selectedItem.value && selectedItem.value.type !== 'folder') {
          const res = await getFileInfo(selectedItem.value.path)
          fileInfo.value = res.data
          fileInfoDialogVisible.value = true
        }
        break
      case 'preview':
        if ('type' in selectedItem.value) {
          try {
            const { data } = await getPreviewUrl(selectedItem.value.path)
            previewUrl.value = data.url
            previewType.value = data.type
            previewTitle.value = selectedItem.value.name
            previewPath.value = selectedItem.value.path
            previewVisible.value = true
          } catch (error) {
            ElMessage.error('获取预览地址失败')
          }
        }
        break
    }
  } catch (error) {
    ElMessage.error('操作失败')
  }

  contextMenuVisible.value = false
}

// 刷新列表时也重置分页参数
const refreshList = () => {
  pageParams.value.marker = ''
  fetchFileList()
}

// 关闭右键菜单
const closeContextMenu = () => {
  contextMenuVisible.value = false
}

// 加载更多文件
const loadMore = () => {
  if (pageParams.value.marker) {
    fetchFileList()
  }
}

// 监听滚动加载更多
const handleScroll = (e: Event) => {
  const target = e.target as HTMLElement
  if (
    target.scrollHeight - target.scrollTop - target.clientHeight < 50 &&
    pageParams.value.marker
  ) {
    loadMore()
  }
}

// 处理下载
const handleDownload = async (path: string) => {
  try {
    const { data } = await getDownloadUrl(path)
    const response = await fetch(data.url)
    const blob = await response.blob()
    const blobUrl = window.URL.createObjectURL(blob)
    
    const a = document.createElement('a')
    a.href = blobUrl
    a.download = data.file_name
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    window.URL.revokeObjectURL(blobUrl)
  } catch (error) {
    ElMessage.error('下载失败')
  }
}

onMounted(() => {
  fetchFileList()
  document.addEventListener('click', closeContextMenu)
  // 添加滚动监听
  const fileList = document.querySelector('.file-list')
  if (fileList) {
    fileList.addEventListener('scroll', handleScroll)
  }
})

onUnmounted(() => {
  document.removeEventListener('click', closeContextMenu)
  // 移除滚动监听
  const fileList = document.querySelector('.file-list')
  if (fileList) {
    fileList.removeEventListener('scroll', handleScroll)
  }
})
</script>

<style scoped lang="scss">
.file-manager-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #f5f7fa;
}

.content-area {
  flex: 1;
  overflow: hidden;
}

/* 修改图片预览组件样式 */
.el-image-viewer__wrapper {
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
</style>